﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net.Mail;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using MassMailing.WPF.Commands;
using MassMailing.WPF.Content;

namespace MassMailing.WPF
{
	/// <summary>
	/// Interaction logic for SendingStatusDialogBox.xaml
	/// </summary>
	public partial class SendingStatusDialogBox : Window
	{
		#region Private Fields

		private List<Recipient> _recipients;
		private MassMailingMessage _message;
		private MassMailingMasterCommand _mailingMasterCommand;
		private Task _mailingMasterCommandTask;

		private int _totalEmails;

		#endregion

		#region Properties

		/// <summary>
		/// Emails that were attempted to be sent;
		/// </summary>
        private static readonly DependencyProperty _sent = DependencyProperty.Register("Sent", typeof(int), typeof(SendingStatusDialogBox), new FrameworkPropertyMetadata(0));
        public int Sent
        {
            get
            {
                return (int)GetValue(_sent);
            }
            set
            {
                SetValue(_sent, value);
            }
        }

        /// <summary>
        /// Total Emails that will be attempted to send.
        /// </summary>
        public int Total
        {
            get
            {
                return _totalEmails;
            }
        }

		/// <summary>
		/// Emails that were successfully sent.
		/// </summary>
        private static readonly DependencyProperty _success = DependencyProperty.Register("Success", typeof(int), typeof(SendingStatusDialogBox), new FrameworkPropertyMetadata(0));
		public int Success
        {
            get
            {
                return (int)GetValue(_success);
            }
            set
            {
                SetValue(_success, value);
                SetValue(_percentageComplete, PercentageComplete);
                SetValue(_percentageCompleteFormattedString, PercentageCompleteFormattedString);
            }
        }

		/// <summary>
		/// Emails that had errors went sent.
		/// </summary>
        private static readonly DependencyProperty _error = DependencyProperty.Register("Error", typeof(int), typeof(SendingStatusDialogBox), new FrameworkPropertyMetadata(0));
		public int Error
        {
            get
            {
                return (int)GetValue(_error);
            }
            set
            {
                SetValue(_error, value);
                SetValue(_percentageComplete, PercentageComplete);
                SetValue(_percentageCompleteFormattedString, PercentageCompleteFormattedString);
            }
        }

		/// <summary>
		/// A integer truncated of the percentage completed of email sent.
		/// </summary>
        private static readonly DependencyProperty _percentageComplete = DependencyProperty.Register("PercentageComplete", typeof(double), typeof(SendingStatusDialogBox), new FrameworkPropertyMetadata(0.0));
		public double PercentageComplete
		{
			get
			{
				if (_totalEmails < 1)
				{
					return 0;
				}

				double totalSent = (double)Success + (double)Error;
				double percentComplete = totalSent / (double)_totalEmails;

				return percentComplete * 100.0;
			}
		}

		/// <summary>
		/// The percentage that is completed as a formatted string.
		/// </summary>
        private static readonly DependencyProperty _percentageCompleteFormattedString =
            DependencyProperty.Register("PercentageCompleteFormattedString", typeof(string), typeof(SendingStatusDialogBox), new FrameworkPropertyMetadata("0%"));
		public string PercentageCompleteFormattedString
		{
			get
			{
				return string.Format("{0:0.#}%", PercentageComplete);
			}
		}

		#endregion

		#region Constructors

		/// <summary>
		/// Default Constructor
		/// </summary>
		/// <param name="recipients">The recipients to use to send the message with.</param>
		/// <param name="message">The message to send to the recipients.</param>
		public SendingStatusDialogBox(List<Recipient> recipients, MassMailingMessage message)
		{
            _totalEmails = recipients.Count;

			InitializeComponent();

			_recipients = recipients;
			_message = message;
			this.DataContext = this;
		}

		#endregion

		#region Event Handlers

		/// <summary>
		/// The event handler for the all messages sent event on the mailing master command.
		/// </summary>
		private void MassMailingMasterCommand_AllMessagesSent(object sender, EventArgs e)
		{
			Action action = () => btnDone.IsEnabled = true;
            InvokeOnUIThread(action);
		}

		/// <summary>
		/// The event handler for the message sent event on the mailing master command.
		/// </summary>
		private void MassMailingMasterCommand_MessageSent(object sender, AsyncCompletedEventArgs e)
		{
			if (!e.Cancelled && e.Error == null)
			{
				Action action = () => Sent++;
                InvokeOnUIThread(action);
			}
		}

		/// <summary>
		/// The event handler for the send completed event on the mailing master command.
		/// </summary>
		private void MassMailingMasterCommand_SendCompleted(object sender, AsyncCompletedEventArgs e)
		{
            Action action = () =>
            {
                if (e.Cancelled)
                {
                    txtLog.Text += string.Format("[{0}] Send canceled.", e.UserState) + Environment.NewLine;
                }
                if (e.Error != null)
                {
                    Error++;
                    txtLog.Text += string.Format("[{0}] Error: {1}", e.UserState, e.Error) + Environment.NewLine;
                }
                else
                {
                    Success++;
                }
            };

            InvokeOnUIThread(action);
		}

		/// <summary>
		/// The event handler for the loaded event for the window.
		/// </summary>
		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			Sent = 0;
			Success = 0;
			Error = 0;
			txtLog.Text = string.Empty;

			_mailingMasterCommand = new MassMailingMasterCommand(_recipients, _message);
			_mailingMasterCommand.AllMessagesSent += new EventHandler(MassMailingMasterCommand_AllMessagesSent);
			_mailingMasterCommand.MessageSent += new AsyncCompletedEventHandler(MassMailingMasterCommand_MessageSent);
			_mailingMasterCommand.SendCompleted += new SendCompletedEventHandler(MassMailingMasterCommand_SendCompleted);
            _mailingMasterCommandTask = _mailingMasterCommand.Execute(true);
		}

		#endregion

        #region Methods

        /// <summary>
        /// Makes sure the action is invoked on the UI thread.
        /// </summary>
        /// <param name="action">The action to perform.</param>
        private void InvokeOnUIThread(Action action)
        {
            if (Dispatcher.CheckAccess())
            {
                action();
            }
            else
            {
                Dispatcher.Invoke(action, DispatcherPriority.Normal);
            }
        }

        #endregion
    }
}
